import 'dart:io';
import 'dart:math';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:giwiki/entities/entities.dart';
import 'package:giwiki/entities/entities_data.dart';

import '../components/info_dialog.dart';

class CharacterDetailScreen extends StatefulWidget {
  final Character c;

  const CharacterDetailScreen(this.c, {super.key});

  @override
  State<StatefulWidget> createState() => _CharacterDetailScreenState();
}

class _CharacterDetailScreenState extends State<CharacterDetailScreen> {
  final ScrollController _scrollController = ScrollController();

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;
    var sw = min(size.width, size.height);
    var sh = max(size.width, size.height);
    var imageSize = sw - 40;
    return Scaffold(
      extendBodyBehindAppBar: true,
      body: Stack(
        children: [
          ListView(
            controller: _scrollController,
            padding: EdgeInsets.zero,
            children: [
              SafeArea(
                bottom: false,
                child: Container(),
              ),
              Stack(children: [
                _cCard(imageSize, size.width < size.height),
                Align(
                  alignment: Alignment.topRight,
                  child: Padding(
                    padding: const EdgeInsets.only(right: 10, top: 12),
                    child: _moreMatInfoIcon(imageSize),
                  ),
                ),
              ]),
              Container(height: 10),
              _descCard(widget.c.desc),
              Container(height: 10),
              _skillCard(),
              SafeArea(
                top: false,
                child: Container(),
              ),
            ],
          ),
          _buildReturn(),
        ],
      ),
    );
  }

  Widget _buildReturn() {
    return SafeArea(
      child: Align(
        alignment: Alignment.topLeft,
        child: IconButton(
          icon: const Icon(
            Icons.arrow_back,
            color: Colors.white,
            shadows: [
              Shadow(
                color: Colors.black,
                offset: Offset(1, 1),
                blurRadius: 1,
              ),
            ],
          ),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ),
    );
  }

  Widget _cCard(double imageSize, bool isPortrait) {
    return Card(
      color: const Color(0xff27363e),
      clipBehavior: Clip.hardEdge,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(8.0)),
      ),
      child: Column(
        children: [
          Container(height: 25),
          Text(
            widget.c.name,
            style: TextStyle(
              color: elementColor(widget.c.element, Colors.white),
              fontSize: 24,
              fontWeight: FontWeight.bold,
            ),
          ),
          Container(height: 12),
          Text(
            "★" * widget.c.grade,
            style: const TextStyle(
              color: Colors.white,
              fontSize: 14,
              fontWeight: FontWeight.bold,
            ),
          ),
          Container(height: 8),
          if (isPortrait && imageSize < 400)
            SizedBox(
              width: imageSize,
              height: imageSize * 0.8,
              child: Image.file(
                File('$repo/pics/Gacha/${widget.c.nameEnglish}.png'),
                fit: BoxFit.cover,
              ),
            ),
          if (!(isPortrait && imageSize < 500))
            SizedBox(
              width: imageSize,
              child: Image.file(
                File('$repo/pics/Gacha/${widget.c.nameEnglish}.png'),
              ),
            ),
          const Text(
            "",
            style: TextStyle(
              color: Colors.white,
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          Text.rich(
            textAlign: TextAlign.center,
            TextSpan(
              children: [
                _buildText(widget.c.constellation),
                WidgetSpan(child: Container(width: 18)),
                _buildText(widget.c.title),
                WidgetSpan(child: Container(width: 18)),
                _buildText(widget.c.belong),
              ],
            ),
          ),
          const Text(
            "",
            style: TextStyle(
              color: Colors.white,
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          Text(
            " ( ${_matText(widget.c.talentmat)} )",
            style: TextStyle(
              color: Colors.white.withOpacity(.7),
              fontWeight: FontWeight.bold,
            ),
          ),
          Container(height: 12),
          Text.rich(
            textAlign: TextAlign.center,
            TextSpan(
              children: [
                _buildElementIcon(widget.c.element),
                WidgetSpan(child: Container(width: 18)),
                _buildItemMatIcon(widget.c.weekmat, imageSize),
                WidgetSpan(child: Container(width: 18)),
                _buildItemMatIcon(widget.c.talentmatt, imageSize),
                WidgetSpan(child: Container(width: 18)),
                _buildItemMatIcon(widget.c.ascmat, imageSize),
                WidgetSpan(child: Container(width: 18)),
                _buildItemMatIcon(widget.c.commonmatt, imageSize),
                WidgetSpan(child: Container(width: 18)),
                _buildItemMatIcon(widget.c.specialitymat, imageSize),
              ],
            ),
          ),
          Container(height: 12),
        ],
      ),
    );
  }

  Widget _descCard(String desc) {
    return Card(
      color: const Color(0xff27363e),
      clipBehavior: Clip.hardEdge,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(8.0)),
      ),
      child: Padding(
        padding: const EdgeInsets.all(10),
        child: Text(
          desc,
          style: const TextStyle(
            color: Colors.white,
            fontSize: 16,
          ),
        ),
      ),
    );
  }

  Widget _skillCard() {
    var skillInfoOption = skillInfosMap[widget.c.nameEnglish];
    if (skillInfoOption == null) {
      return Container();
    }
    var skillInfo = skillInfoOption;
    if (skillInfo.ver.isEmpty) {
      return Container();
    }
    var verKeys = [...skillInfo.ver.keys];
    verKeys.sort((a, b) => -a.compareTo(b));
    var key = verKeys[0];
    return Column(
      children: [
        _buildBattleSkillsCard(skillInfo.ver[key]!.battleSkills),
        const SizedBox(height: 10),
        _buildPassiveSkillsCard(skillInfo.ver[key]!.passiveSkills),
        const SizedBox(height: 10),
        _buildConstellationsCard(skillInfo.ver[key]!.constellations),
      ],
    );
  }

  Widget _buildBattleSkillsCard(List<BattleSkill> battleSkills) {
    if (battleSkills.isEmpty) {
      return Container();
    }
    return Card(
      color: const Color(0xff27363e),
      clipBehavior: Clip.hardEdge,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(8.0)),
      ),
      child: Column(
        children: [
          _skillsTitle("战斗天赋"),
          for (var v in battleSkills)
            _skillInfo(v.icon, v.name, v.desc, paramDesc: v.paramDesc),
        ],
      ),
    );
  }

  Widget _buildPassiveSkillsCard(List<PassiveSkill> passiveSkills) {
    if (passiveSkills.isEmpty) {
      return Container();
    }
    return Card(
      color: const Color(0xff27363e),
      clipBehavior: Clip.hardEdge,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(8.0)),
      ),
      child: Column(
        children: [
          _skillsTitle("固有天赋"),
          for (var v in passiveSkills) _skillInfo(v.icon, v.name, v.desc),
        ],
      ),
    );
  }

  Widget _buildConstellationsCard(List<Constellation> constellations) {
    if (constellations.isEmpty) {
      return Container();
    }
    return Card(
      color: const Color(0xff27363e),
      clipBehavior: Clip.hardEdge,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(8.0)),
      ),
      child: Column(
        children: [
          _skillsTitle("命座"),
          for (var v in constellations) _skillInfo(v.icon, v.name, v.desc),
        ],
      ),
    );
  }

  InlineSpan _buildText(String text) {
    return TextSpan(
      text: text,
      style: const TextStyle(
        color: Colors.white,
        fontSize: 18,
        fontWeight: FontWeight.bold,
      ),
    );
  }

  InlineSpan _buildElementIcon(String element) {
    return WidgetSpan(
      alignment: PlaceholderAlignment.middle,
      child: Image.file(
        File("$repo/pics/Csxylic/$element.png"),
        width: 36,
      ),
    );
  }

  InlineSpan _buildItemMatIcon(int weekmat, double imageSize) {
    var item = itemsMap[weekmat];
    if (item == null) {
      return const TextSpan();
    }
    var itemIcon = item.icon;
    return WidgetSpan(
      alignment: PlaceholderAlignment.middle,
      child: GestureDetector(
        onTap: () async {
          await infoDialog(
            context,
            canPop: true,
            backgroundColor: const Color(0xff27363e),
            title: Text.rich(TextSpan(children: [
              WidgetSpan(
                alignment: PlaceholderAlignment.middle,
                child: Image.file(
                  File("$repo/pics/Item/$itemIcon.png"),
                  width: 36,
                ),
              ),
              TextSpan(
                text: item.name,
                style: const TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ])),
            content: SizedBox(
              width: imageSize,
              child: Column(
                children: [
                  if (item.desc.isNotEmpty)
                    Html(
                      data: item.src.join("<br>"),
                      style: {
                        "html": Style(
                          color: Colors.white.withAlpha(200),
                          fontSize: FontSize(12),
                        ),
                      },
                    ),
                  if (item.desc.isNotEmpty) Container(height: 10),
                  Html(
                    data: item.desc,
                    style: {
                      "html": Style(
                        color: Colors.white,
                        fontSize: FontSize(16),
                      ),
                    },
                  ),
                ],
              ),
            ),
          );
        },
        child: Image.file(
          File("$repo/pics/Item/$itemIcon.png"),
          width: 36,
        ),
      ),
    );
  }

  Widget _skillsTitle(String title) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        return SizedBox(
          width: constraints.maxWidth,
          child: Padding(
            padding: const EdgeInsets.only(
              left: 20,
              top: 10,
              bottom: 10,
            ),
            child: Text(
              title,
              textAlign: TextAlign.left,
              style: const TextStyle(
                color: Colors.white,
              ),
            ),
          ),
        );
      },
    );
  }

  Widget _moreMatInfoIcon(double imageSize) {
    return GestureDetector(
      onTap: () {
        showMatCountDialog(context, widget.c, imageSize);
      },
      child: const Icon(
        Icons.unfold_more_outlined,
        color: Colors.white,
        size: 28,
      ),
    );
  }

  Widget _skillInfo(
    String icon,
    String name,
    String desc, {
    List<BattleSkillParamDesc>? paramDesc,
  }) {
    ExpansionTileController controller = ExpansionTileController();
    Widget title = Text(
      name,
      style: const TextStyle(
        color: Colors.white,
        fontSize: 18,
        fontWeight: FontWeight.bold,
      ),
    );
    var tile = ExpansionTile(
      controller: controller,
      collapsedBackgroundColor: const Color(0x11000000),
      initiallyExpanded: false,
      leading: Image.file(
        File("$repo/pics/Skill/${icon}.png"),
        width: 36,
      ),
      title: title,
      children: [
        Container(
          padding: _skillInnerPadding,
          child: Html(
            data: desc
                .replaceAll("<color", "<font")
                .replaceAll("/color>", "/font>"),
            style: {
              "html": Style(
                color: Colors.white,
                fontSize: FontSize(16),
              ),
            },
          ),
        ),
        Padding(
          padding: _skillInnerPadding,
          child: LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
              return SizedBox(
                width: constraints.maxWidth,
                height: 30,
                child: Text.rich(
                  TextSpan(
                    children: [
                      if (paramDesc != null)
                        TextSpan(
                          text: "倍率",
                          style: const TextStyle(color: Colors.white),
                          recognizer: TapGestureRecognizer()
                            ..onTap = () {
                              displayBattleSkillParamDesc(
                                context,
                                icon,
                                name,
                                paramDesc,
                              );
                            },
                        ),
                      if (paramDesc != null)
                        WidgetSpan(child: Container(width: 40)),
                      TextSpan(
                        text: "折叠",
                        style: const TextStyle(color: Colors.white),
                        recognizer: TapGestureRecognizer()
                          ..onTap = () {
                            controller.collapse();
                          },
                      ),
                      WidgetSpan(child: Container(width: 20)),
                    ],
                  ),
                  textAlign: TextAlign.right,
                ),
              );
            },
          ),
        ),
      ],
    );
    return Container(
      decoration: const BoxDecoration(
        border: Border(
          top: BorderSide(
            width: .5,
            color: Color(0x33000000),
          ),
        ),
      ),
      child: tile,
    );
  }

  Future displayBattleSkillParamDesc(
    BuildContext context,
    String icon,
    String name,
    List<BattleSkillParamDesc> paramDesc,
  ) async {
    await infoDialog(
      context,
      backgroundColor: const Color(0xff27363e),
      title: Text.rich(
        TextSpan(
          children: [
            WidgetSpan(
              alignment: PlaceholderAlignment.middle,
              child: Image.file(
                File("$repo/pics/Skill/$icon.png"),
                width: 36,
              ),
            ),
            TextSpan(
              text: name,
              style: const TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
              ),
            ),
          ],
        ),
      ),
      content: Column(children: [
        for (var v in paramDesc)
          Padding(
            padding: _skillInnerPadding,
            child: Row(
              children: [
                Expanded(
                  flex: 1,
                  child: Text(
                    v.desc,
                    style: const TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                Expanded(
                  flex: 1,
                  child: Text(
                    v.paramLevelList.last,
                    textAlign: TextAlign.right,
                    style: const TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
              ],
            ),
          ),
      ]),
    );
  }

  void showMatCountDialog(BuildContext context, Character c, double imageSize) {
    infoDialog(
      context,
      canPop: true,
      backgroundColor: const Color(0xff27363e),
      title:
          Text("${c.name} - 材料", style: const TextStyle(color: Colors.white)),
      content: Column(children: [
        Container(height: 10),
        Table(
            defaultVerticalAlignment: TableCellVerticalAlignment.middle,
            children: [
              TableRow(children: [
                Text.rich(
                  TextSpan(children: [_buildItemMatIcon(c.weekmat, imageSize)]),
                ),
                const Text("18", style: TextStyle(color: Colors.white)),
                Text.rich(
                  TextSpan(children: [_buildItemMatIcon(c.ascmat, imageSize)]),
                ),
                const Text("46", style: TextStyle(color: Colors.white)),
                Text.rich(
                  TextSpan(children: [
                    _buildItemMatIcon(c.specialitymat, imageSize)
                  ]),
                ),
                const Text("168", style: TextStyle(color: Colors.white)),
              ]),
              TableRow(children: [
                Text.rich(
                  TextSpan(
                      children: [_buildItemMatIcon(c.talentmatt, imageSize)]),
                ),
                const Text("114", style: TextStyle(color: Colors.white)),
                if (itemsMap.containsKey(c.talentmatt - 1)) ...[
                  Text.rich(
                    TextSpan(children: [
                      _buildItemMatIcon(c.talentmatt - 1, imageSize)
                    ]),
                  ),
                  const Text("63", style: TextStyle(color: Colors.white)),
                ],
                if (itemsMap.containsKey(c.talentmatt - 2)) ...[
                  Text.rich(
                    TextSpan(children: [
                      _buildItemMatIcon(c.talentmatt - 2, imageSize)
                    ]),
                  ),
                  const Text("9", style: TextStyle(color: Colors.white)),
                ],
              ]),
              TableRow(children: [
                Text.rich(
                  TextSpan(
                      children: [_buildItemMatIcon(c.commonmatt, imageSize)]),
                ),
                const Text("129", style: TextStyle(color: Colors.white)),
                if (itemsMap.containsKey(c.commonmatt - 1)) ...[
                  Text.rich(
                    TextSpan(children: [
                      _buildItemMatIcon(c.commonmatt - 1, imageSize)
                    ]),
                  ),
                  const Text("96", style: TextStyle(color: Colors.white)),
                ],
                if (itemsMap.containsKey(c.commonmatt - 2)) ...[
                  Text.rich(
                    TextSpan(children: [
                      _buildItemMatIcon(c.commonmatt - 2, imageSize)
                    ]),
                  ),
                  const Text("36", style: TextStyle(color: Colors.white)),
                ],
              ]),
            ]),
        Container(height: 10),
      ]),
    );
  }
}

String _matText(int talentmat) {
  switch (talentmat) {
    case 1:
      return "一 / 四 / 日";
    case 2:
      return "二 / 五 / 日";
    case 3:
      return "三 / 六 / 日";
    default:
      return "";
  }
}

Color elementColor(String element, Color defaultColor) {
  switch (element) {
    case "Water":
      return const Color(0xff81bffd);
    case "Elec":
      return const Color(0xffffaafc);
    case "Grass":
      return const Color(0xff96fd8f);
    case "Fire":
      return const Color(0xffff9999);
    case "Rock":
      return const Color(0xfffde69d);
    case "Wind":
      return const Color(0xff78f2cf);
    case "Ice":
      return const Color(0xff98ffff);
    default:
      return defaultColor;
  }
}

const _skillInnerPadding = EdgeInsets.only(
  left: 10,
  right: 10,
  top: 3,
  bottom: 8,
);
